#include "../StdInc.h"

namespace GSTrader
{
	namespace QuoteService
	{
		CTimer::CTimer(TimerFunc& pFunc, CTimePoint& t, CMsg* pMsg) : m_pTimerFunc(pFunc), m_pMsg(pMsg), m_nTimerId(-1)
		{
			m_nType = msgOnTimer;
			m_time = t;

			m_pTimeObject = NULL;
		}

		CTimer::~CTimer()
		{

		}

		CTimer::CTimer(const CTimer& r)
		{
			*this = r;
		}

		CTimer& CTimer::operator = (const CTimer& r)
		{
			CMsg::operator = (r);

			m_pMsg = r.m_pMsg;
			m_pTimeObject = r.m_pTimeObject;
			m_pTimerFunc = r.m_pTimerFunc;
			return *this;
		}

		void CTimer::Execute()
		{
			if (m_pTimerFunc)
			{
				m_pTimerFunc(m_time, m_pMsg);
			}
		}

		CTimerQueue::CTimerQueue()
		{

		}

		CTimerQueue::~CTimerQueue()
		{
			RemoveAll();
		}

		void CTimerQueue::RemoveAll()
		{
			for (auto p : m_Queue)
			{
				_delete(p)
			}

			m_Queue.clear();
		}

		void CTimerQueue::RemoveTimer(int nTimerId)
		{
			if (nTimerId < 0)
				return;

			int i = 0;
			for (auto x : m_Queue)
			{
				CTimer* pTimerPtr = (CTimer*)(x);
				if (pTimerPtr && pTimerPtr->m_nTimerId == nTimerId)
				{
					_delete(pTimerPtr)
					m_Queue.erase(m_Queue.begin() + i);
					if (i == 0)
					{
						if (m_Queue.size() > 0)
						{
							m_time = m_Queue[0]->GetTime();
						}
					}
					break;
				}
				i++;
			}
		}

		CRuntimeDateTime::CRuntimeDateTime( int nType, int nMode) :  m_nType(nType), m_nMode(nMode)
		{
			m_nNextId = 0;
			m_pTimerQueue = new CTimerQueue;
			if (nType == timeExchange)
			{
				m_time = time_t(0);
			}

			if (nMode == runClient)
			{
				m_nMode = runRealtime;
			}
		}

		CRuntimeDateTime::~CRuntimeDateTime()
		{
			_delete(m_pTimerQueue)
		}

		CTimePoint CRuntimeDateTime::GetNowTime()
		{
			return CTimePoint::Now();
		}

		CTimePoint CRuntimeDateTime::GetTime()
		{
			if (m_nType == timeExchange)
				return m_time;

			if (m_nMode != runRealtime)
				return m_time;

			return CTimePoint::Now();
		}

		bool CRuntimeDateTime::SetTime(CTimePoint t)
		{
			if (m_nType == timeExchange && t != m_time)
			{
				if (t < m_time)
				{
					return false;
				}
				else
				{
					m_time = t;
				}
			}
			else if (m_nMode != runSimulation) 
			{
				m_time = t;
			}
			else
			{
				if ( t < m_time)
				{
					return false;
				}

				m_time = t;
			}

			return true;
		}


		int CRuntimeDateTime::AddTimer(CTimer* pTimer)
		{
			if (pTimer == NULL || pTimer->GetTime() < GetTime())
			{
				return -1;
			}

			pTimer->m_nTimerId = m_nNextId++;
			pTimer->m_pTimeObject = this;
			m_pTimerQueue->Push(pTimer);

			return pTimer->m_nTimerId;
		}

		int CRuntimeDateTime::AddTimer3(TimerFunc& pFunc, CTimePoint& t, CMsg* pMsg)
		{
			CTimer* pTimer = new CTimer(pFunc, t, pMsg);
			return AddTimer(pTimer);
		}

		void CRuntimeDateTime::RemoveTimer(int nId)
		{
			m_pTimerQueue->RemoveTimer(nId);
		}

	}
}